local jass = require 'jass.common'
local japi = require 'jass.japi'
local japi2 = require 'util.japi2'

local math = math
local math_max = math.max
local math_min = math.min
local math_sin = math.sin
local math_cos = math.cos
local math_modf = math.modf
local math_floor = math.floor

local w2s = ac.frame.w2s
local portrait = ac.frame.portrait
local get_location_height = ac.point.get_location_height
local get_unit_overhead = ac.message.unit_overhead
local getx = jass.GetUnitX
local gety = jass.GetUnitY
local getz = jass.GetUnitFlyHeight

local PPI = 1.08 -- 别问 问就是常量

local handle_manager = handle_manager_class:create()

local texttag = {}
setmetatable(texttag, texttag)

ac.texttag2 = texttag

-- 默认位置
texttag.position = ac.point(0, 0)

-- 更新帧率
texttag.FRAME = 80

-- 所有漂浮文字
texttag.alltexttag = {}

-- 所有要更新的漂浮文字
texttag.texttagmap = {}

-- 存放所有预设textframe
texttag.textframes = {}

-- 存放池子
texttag.textpool = { }

-- 预设数量
texttag.handle_max = 64

-- 默认字体
--texttag.font = "fonts\\font.ttf"

-- 引用统计
texttag.debug_count = 0

function texttag.globals()
    texttag.handle_count = texttag.handle_count + 1
    if texttag.handle_count <= texttag.handle_max then 
        return texttag.textframes[texttag.handle_count]
    end 
end 

function texttag.allocate()
    local textframe = texttag.textpool[1]
    if not textframe then 
        return texttag.globals()
    end 
    table.remove(texttag.textpool, 1)
    return textframe
end 

function texttag.free(textframe)
    table.insert(texttag.textpool, textframe)
end

function texttag.create(data)
    local tag = setmetatable(data or {}, texttag)
    local handle = handle_manager:allocate()
    local textframe = texttag.allocate()
    if textframe then 
        textframe.texttag = tag
        tag.textframe = textframe
    end 
    tag.handle = handle
    texttag.alltexttag[handle] = tag
    texttag.texttagmap[handle] = tag
    tag:init()
    texttag.debug_count = texttag.debug_count + 1
    return tag
end

-- 创建漂浮文字
function texttag:__call(data)
    if not data.target then
        log.error('没有目标')
        return
    end
    return texttag.create(data)
end

local mt = {}
texttag.__index = mt

-- 结构
mt.type = 'texttag'

-- 伪句柄
mt.handle = 0

-- 文本
mt.text = ""

-- 实体控件
mt.textframe = nil

-- 高度偏移
mt.height = 0

-- 目标
mt.target = nil

-- 颜色
mt.color = 0xffffffff

-- 透明度
mt.alpha = 255

-- 字体大小
mt.font_size = 24

-- 淡化时间
mt.fadepoint = -1

-- 持续时间
mt.lifespan = -1

-- x轴移动速率
mt.xvel = 0

-- y轴移动速率
mt.yvel = 0

-- 是否显示
mt.show_flag = true

-- 暂停
mt.suspended_flag = false

function mt:init()
    self.offset_x = 0
    self.offset_y = 0
    self.lifeClock = 0
    self.fadeClock = 0
    self.velocity_font_size = 0
    self.world_x = 0
    self.world_y = 0
    self.world_z = 0
    self.suspended_flag = false
    self:set_alpha(self.alpha)
    self:set_color(self.color)
    self:set_font_size(self.font_size)
    self:set_text(self.text)
    if self.target then
        texttag.ingore_flag = true
        if self.target.type == 'unit' then
            self:set_tagpos_unit(self.target)
        else
            self:set_tagpos(self.target:get_point())
        end
        texttag.ingore_flag = false
    end
    if self.show_flag == false then
        self:hide()
    else
        self:show()
    end
end

-- 设置文本
function mt:set_text(text)
    self.text = text
    if self.textframe then
        self.textframe:set_text(self.text)
    end
end

-- 绑定到 1单位 2z偏移位置
function mt:set_tagpos_unit(unit, height)
    if not unit or unit.removed then return end
    local point = unit:get_point()
    local wx, wy = point:get()
    self.height = height
    self.world_x = wx
    self.world_y = wy
    self.world_z = self.height + getz(unit.handle) + get_unit_overhead(unit.handle) + get_location_height(wx, wy)
    self:update_world_position()
end

-- 绑定到点 1点 2z偏移位置
function mt:set_tagpos(point, height)
    if not point then return end
    local wx, wy = point:get()
    self.height = height
    self.world_x = wx
    self.world_y = wy
    self.world_z = self.height + get_location_height(wx, wy)
    self:update_world_position()
end

-- 设置颜色
function mt:set_color(color)
    self.color = color
    if self.textframe then
        japi.FrameSetTextColor(self.textframe.handle, self.color)
    end
end

-- 获取透明度
function mt:get_alpha()
    return self.alpha
end

-- 设置透明度
function mt:set_alpha(alpha)
    self.alpha = math_modf(alpha)
    if self.alpha < 0 then
        self.alpha = 0
    elseif self.alpha > 255 then
        self.alpha = 255
    end
    if self.textframe then
        japi2.FrameSetFontAlpha(self.textframe.handle, self.alpha)
    end
end

-- 设置字体大小
function mt:set_font_size(font_size)
    self.font_size = font_size
    if self.textframe then
        self.velocity_font_size = self.font_size * 0.071 / 128
        japi2.FrameSetFontHeight(self.textframe.handle, self.velocity_font_size)
    end
end

-- 获取字体大小
function mt:get_font_size()
    return self.font_size
end

-- 设置时间 超过后自动删除 (其实是回到池子)
function mt:set_lifespan(time)
    self.lifespan = time
    self.lifeClock = 0
end

-- 设置已存在时间
function mt:set_age(time)
    self.lifeClock = time
end

-- 设置淡化时间 超过后开始淡化 最多1秒后完全消失
function mt:set_fadepoint(fade)
    self.fadepoint = fade
    self.fadeClock = 0
end

-- 设置永久显示 (其实是移除 时间限制)
function mt:set_permanent(flag)
    self.lifespan = -1
    self.lifeClock = 0
end

-- 暂停漂浮文字的移动和生命计时
function mt:set_suspended(flag)
    if flag == true then
        self.suspended_flag = true
    else
        self.suspended_flag = false
    end
end

-- 设置移动x和y的速率 会重置到初始位置 然后开始移动
function mt:set_velocity(xvel, yvel)
    self.xvel = xvel
    self.yvel = yvel
    self.offset_x = 0
    self.offset_y = 0
    if self.textframe then
        self.offset_y = japi.FrameGetTextHeight(self.textframe.handle) / 0.6 * 1080 * 0.5
    end
    self:update_world_position()
end
 
-- 设置移动方向和速率
function mt:set_velocity2(angle, speed)
    local dist = speed * 0.071 / 128
    self:set_velocity(dist * math_cos(angle), dist * math_sin(angle))
end

-- 是否显示
function mt:is_show()
    return self.show_flag
end

-- 设置显示
function mt:show()
    self.show_flag = true
    if self.textframe then
        self.textframe:show()
        texttag.update_texttag(self, 0)
    end
end

-- 设置隐藏
function mt:hide()
    self.show_flag = false
    if self.textframe then
        self.textframe:hide()
    end
end

-- 绘制回调
function mt:on_update(elapse)
end

function mt:remove()
    if self.removed then
        return
    end
    local handle = self.handle
    local textframe = self.textframe
    self.textframe = nil
    if textframe then
        textframe:hide()
        textframe.texttag = nil
        texttag.free(textframe)
    end
    texttag.alltexttag[handle] = nil
    texttag.texttagmap[handle] = nil
    self.handle = 0
    texttag.debug_count = texttag.debug_count - 1
end

function mt:update_world_position()
    if texttag.ingore_flag then
        return
    end

    if not self:is_show() then
        return
    end

    if self.removed then
        return
    end

    if not self.textframe then
        return
    end

    local x = self.world_x
    local y = self.world_y
    local z = self.world_z

    local sx, sy = w2s(x, y, z)

    if sx == nil or sx < 0 or sy < 32 or sx > 1920 or sy > 768 then
        self.textframe:hide()
    else
        japi.FrameSetAbsolutePoint(self.textframe.handle, 0, (sx + self.offset_x) / 1920 * 0.8,
            (1080 - (sy + self.offset_y)) / 1080 * 0.6 + japi.FrameGetTextHeight(self.textframe.handle))
        self.textframe:show()
    end
end

function texttag.update_texttag(tag, elapse)
    tag:on_update(elapse)
    if not tag.removed and tag.show_flag then
        tag.offset_x = tag.offset_x + (tag.xvel * elapse * PPI)
        tag.offset_y = tag.offset_y - (tag.yvel * elapse * PPI)
        if tag.fadepoint >= 0 then
            if tag.fadeClock < tag.fadepoint then
                tag.fadeClock = tag.fadeClock + elapse
            else
                if tag.alpha > 0 then
                    tag:set_alpha(tag.alpha - elapse * 255)
                end
            end
        end
        tag:update_world_position()
    end
end

function texttag.update1(_, elapse)
    for _, tag in pairs(texttag.texttagmap) do
        if not tag.suspended_flag then
            texttag.update_texttag(tag, elapse)
        end
    end
end

function texttag.update2()
    local removes = {}
    for _, tag in pairs(texttag.alltexttag) do
        if not tag.suspended_flag then
            if tag.lifespan >= 0 then
                if tag.lifeClock < tag.lifespan then
                    tag.lifeClock = tag.lifeClock + texttag.FRAME * 0.001
                    if tag.lifeClock >= tag.lifespan then
                        removes[#removes + 1] = tag
                    end
                end
            end
        end
    end
    for _, tag in ipairs(removes) do
        tag:remove()
    end
end

local function init()
    texttag.handle_count = 1
    for i = 1, texttag.handle_max do
        texttag.textframes[i] = class.text:builder {
            parent = portrait,
            font = texttag.font,
            font_size = 23,
            height = 23,
            outline = true,
            shadow_color = 0xff000000,
            shadow_offset_x = 2,
            shadow_offset_y = -2,
            convert_flag = true,
            w = 0,
            h = 0,
            show_flag = false,
        }
    end

    texttag.frame_update = ac.hardware:on("界面绘制")(texttag.update1)
    texttag.cycle_timer = ac.loop(texttag.FRAME, texttag.update2)
end

init()

return texttag
